package com.neusoft.utils.web;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.WebUtils;

import com.neusoft.utils.encrypt.Base64Util;
import com.neusoft.utils.string.StringUtil;




/**
 * HttpServletRequest帮助类
 */
public class RequestUtils {
    private static final   Log log = LogFactory.getLog(RequestUtils.class);
	/**
	 * UTF-8编码
	 */
	public static final String UTF8 = "UTF-8";
	/**
	 * HTTP POST请求
	 */
	public static final String POST = "POST";

	public static HttpServletRequest getRequest() {
		HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		return req;
	}

	public static boolean isWeixin(HttpServletRequest request) {
		String header=((HttpServletRequest) request).getHeader("user-agent");
		String ua = header.toLowerCase();
		if (ua.indexOf("micromessenger") > 0) {// 是微信浏览器
			return true;
		}
		return false;
	}

	public static String getBasePath() {
		String basePath = null;
		try {
			basePath = WebUtils.getRealPath(getRequest().getSession().getServletContext(), "");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return basePath;
	}

	public static Map<String, Object> getUrlParam(HttpServletRequest request) {
		String s = request.getQueryString();
		if(StringUtil.isNull(s)){
			return new HashMap<String, Object>();
		}
		if (s.endsWith("@")) {
			s=s.substring(0,s.length()-1);
		}
		s = StringUtil.substringBefore(s, "&");
		Map<String, Object> param = new HashMap<String, Object>();
		if (null != s && !StringUtil.isBlank(s)) {
			param = RequestUtils.parseQueryStringToMap(Base64Util.decodeStr(s + "=="));
		}
		return param;
	}

	public static String getOrgImgRealPath(String path) {
		if (StringUtil.isBlank(path)) {
			return "";
		}
		path = path.trim();
		int queryParamIndex = path.indexOf('?');
		if (queryParamIndex > 0) {
			path = path.substring(0, queryParamIndex);
		}
	/*	if (path.indexOf("/files/") != -1) {
			String rootPath = SystemConfig.getProperty("nginx.root.path");// 真实位置
			return rootPath + StringUtil.substringAfter(path, "/files/");
		}*/
		String realPath = "";
		try {
			realPath = WebUtils.getRealPath(getRequest().getSession().getServletContext(), path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return realPath;
	}
	public static String getWebRealPath(HttpServletRequest request,String path) {
		if (StringUtil.isBlank(path)) {
			return "";
		}
		path = path.trim();
	/*	if (path.indexOf("/files/") != -1) {
			String rootPath = SystemConfig.getProperty("nginx.root.path");// 真实位置
			return rootPath + StringUtil.substringAfter(path, "/files/");
		}*/
		String realPath = "";
		try {
			realPath = WebUtils.getRealPath(request.getSession().getServletContext(), path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return realPath;
	}
	public static String getWebRealPath(String path) {
		return getWebRealPath(getRequest(),path);
	}

	public static String getContextPath() {
		return getRequest().getContextPath();
	}

	/**
	 * 获取QueryString的参数，并使用URLDecoder以UTF-8格式转码。如果请求是以post方法提交的，
	 * 那么将通过HttpServletRequest#getParameter获取。
	 * 
	 * @param request
	 *            web请求
	 * @param name
	 *            参数名称
	 * @return
	 */
	public static String getQueryParam(HttpServletRequest request, String name) {
		if (StringUtil.isBlank(name)) {
			return null;
		}
		if (request.getMethod().equalsIgnoreCase(POST)) {
			return request.getParameter(name);
		}
		String s = request.getQueryString();
		if (StringUtil.isBlank(s)) {
			return null;
		}
		try {
			s = URLDecoder.decode(s, UTF8);
		} catch (UnsupportedEncodingException e) {
			log.error("encoding " + UTF8 + " not support?", e);
		}
		String[] values = parseQueryString(s).get(name);
		if (values != null && values.length > 0) {
			return values[values.length - 1];
		} else {
			return null;
		}
	}
	public static String[] getParameterValues(HttpServletRequest request, String name) {
		   String[]  result=getParameterValuesSub(request, name);
		   if(null==result){
			   result=getParameterValuesSub(request, name+"[]");
		   }
		   return result;
	}
	private static String[] getParameterValuesSub(HttpServletRequest request, String name) {
		if (StringUtil.isBlank(name)) {
			return null;
		}
		if (request.getMethod().equalsIgnoreCase(POST)) {
			return request.getParameterValues(name);
		}
		String s = request.getQueryString();
		if (StringUtil.isBlank(s)) {
			return null;
		}
		try {
			s = URLDecoder.decode(s, UTF8);
		} catch (UnsupportedEncodingException e) {
			log.error("encoding " + UTF8 + " not support?", e);
		}
		String[] values = parseQueryString(s).get(name);
		if (values != null && values.length > 0) {
			return values;
		} else {
			return null;
		}
	}

	/**
	 * @Title: getQueryParams
	 * @author fengchangyi
	 * @param request
	 * @param type
	 * @return
	 */
	public static Map<String, Object> getQueryParams(HttpServletRequest request) {
		Map<String, String[]> map;
		if (request.getMethod().equalsIgnoreCase(POST)) {
			map = request.getParameterMap();
		} else {
			String s = request.getQueryString();
			if (StringUtil.isBlank(s)) {
				return new HashMap<String, Object>();
			}
			try {
				s = URLDecoder.decode(s, UTF8);
			} catch (UnsupportedEncodingException e) {
				log.error("encoding " + UTF8 + " not support?", e);
			}
			map = parseQueryString(s);
		}

		Map<String, Object> params = new HashMap<String, Object>(map.size());
		int len;
		for (Map.Entry<String, String[]> entry : map.entrySet()) {
			String key = entry.getKey();

			len = entry.getValue().length;
			if (len == 1) {
				params.put(key, entry.getValue()[0]);
			} else if (len > 1) {
				params.put(key, entry.getValue());
			}
		}
		return params;
	}

	/**
	 * 
	 * Parses a query string passed from the client to the server and builds a
	 * <code>HashTable</code> object with key-value pairs. The query string
	 * should be in the form of a string packaged by the GET or POST method,
	 * that is, it should have key-value pairs in the form <i>key=value</i>,
	 * with each pair separated from the next by a &amp; character.
	 * 
	 * <p>
	 * A key can appear more than once in the query string with different
	 * values. However, the key appears only once in the hashtable, with its
	 * value being an array of strings containing the multiple values sent by
	 * the query string.
	 * 
	 * <p>
	 * The keys and values in the hashtable are stored in their decoded form, so
	 * any + characters are converted to spaces, and characters sent in
	 * hexadecimal notation (like <i>%xx</i>) are converted to ASCII characters.
	 * 
	 * @param s
	 *            a string containing the query to be parsed
	 * 
	 * @return a <code>HashTable</code> object built from the parsed key-value
	 *         pairs
	 * 
	 * @exception IllegalArgumentException
	 *                if the query string is invalid
	 * 
	 */
	public static Map<String, Object> parseQueryStringToMap(String s) {
		if (StringUtil.isBlank(s)) {
			return new HashMap<String, Object>();
		}
		Map<String, String[]> map = parseQueryString(s);
		Map<String, Object> params = new HashMap<String, Object>(map.size());
		int len;
		for (Map.Entry<String, String[]> entry : map.entrySet()) {
			String key = entry.getKey();

			len = entry.getValue().length;
			if (len == 1) {
				params.put(key, entry.getValue()[0]);
			} else if (len > 1) {
				params.put(key, entry.getValue());
			}
		}
		return params;
	}

	public static Map<String, String[]> parseQueryString(String s) {
		String valArray[] = null;
		if (s == null) {
			throw new IllegalArgumentException();
		}
		Map<String, String[]> ht = new HashMap<String, String[]>();
		StringTokenizer st = new StringTokenizer(s, "&");
		while (st.hasMoreTokens()) {
			String pair = (String) st.nextToken();
			int pos = pair.indexOf('=');
			if (pos == -1) {
				continue;
			}
			String key = pair.substring(0, pos);
			String val = pair.substring(pos + 1, pair.length());
			if (ht.containsKey(key)) {
				String oldVals[] = (String[]) ht.get(key);
				valArray = new String[oldVals.length + 1];
				for (int i = 0; i < oldVals.length; i++) {
					valArray[i] = oldVals[i];
				}
				valArray[oldVals.length] = val;
			} else {
				valArray = new String[1];
				valArray[0] = val;
			}
			ht.put(key, valArray);
		}
		return ht;
	}

	public static Map<String, String> getRequestMap(HttpServletRequest request, String prefix) {
		return getRequestMap(request, prefix, false);
	}

	public static Map<String, String> getRequestMapWithPrefix(HttpServletRequest request, String prefix) {
		return getRequestMap(request, prefix, true);
	}

	private static Map<String, String> getRequestMap(HttpServletRequest request, String prefix, boolean nameWithPrefix) {
		Map<String, String> map = new HashMap<String, String>();
		Enumeration<String> names = request.getParameterNames();
		String name, key, value;
		while (names.hasMoreElements()) {
			name = names.nextElement();
			if (name.startsWith(prefix)) {
				key = nameWithPrefix ? name : name.substring(prefix.length());
				value = StringUtil.join(request.getParameterValues(name), ',');
				map.put(key, value);
			}
		}
		return map;
	}

	/**
	 * 获取访问者IP
	 * 
	 * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
	 * 
	 * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
	 * 如果还不存在则调用Request .getRemoteAddr()。
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		if (!StringUtil.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if (!StringUtil.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个IP值，第一个为真实IP。
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		} else {
			return request.getRemoteAddr();
		}
	}

	/**
	 * 获得当的访问路径
	 * 
	 * HttpServletRequest.getRequestURL+"?"+HttpServletRequest.getQueryString
	 * 
	 * @param request
	 * @return
	 */
	public static String getLocation(HttpServletRequest request) {
		UrlPathHelper helper = new UrlPathHelper();
		StringBuffer buff = request.getRequestURL();
		String uri = request.getRequestURI();
		String origUri = helper.getOriginatingRequestUri(request);
		buff.replace(buff.length() - uri.length(), buff.length(), origUri);
		String queryString = helper.getOriginatingQueryString(request);
		if (queryString != null) {
			buff.append("?").append(queryString);
		}
		return buff.toString();
	}

	public static String getBaseLocation(HttpServletRequest request) {
		UrlPathHelper helper = new UrlPathHelper();
		StringBuffer buff = request.getRequestURL();
		String uri = request.getRequestURI();
		String origUri = helper.getOriginatingRequestUri(request);
		buff.replace(buff.length() - uri.length(), buff.length(), origUri);
		buff = new StringBuffer(buff.substring(0, buff.length() - uri.length()));
		buff.append(request.getContextPath());
		return buff.toString();
	}
	/**
	 * TODO 获得url
	 * 除去contextpath queryParam
	 * @param request
	 * @return
	 */
	public static  String  getUrl(HttpServletRequest request) {
		String contextPath = request.getContextPath();
		String uri = request.getRequestURI();
		int pathParamIndex = uri.indexOf(';');
		if (pathParamIndex > 0) {
			uri = uri.substring(0, pathParamIndex);
		}
		int queryParamIndex = uri.indexOf('?');
		if (queryParamIndex > 0) {
			uri = uri.substring(0, queryParamIndex);
		}
		if (contextPath.length() > 1) {
			uri = uri.substring(contextPath.length(), uri.length());
		}
		return uri;
	}
	public static  String  getAllUrl(HttpServletRequest request) {
		String url= getUrl(request);
		if(null!=request.getQueryString()&&StringUtil.isNotBlank(request.getQueryString())){
			url=url+"?"+request.getQueryString();
		}
		return url;
	}
	public static String getMACAddress(String ip) {  
        String str = "";  
        String macAddress = "";  
        try {  
            Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);  
            InputStreamReader ir = new InputStreamReader(p.getInputStream());  
            LineNumberReader input = new LineNumberReader(ir);  
            for (int i = 1; i < 100; i++) {  
                str = input.readLine();  
                if (str != null) {  
                    if (str.indexOf("MAC Address") > 1) {  
                        macAddress = str.substring(  
                                str.indexOf("MAC Address") + 14, str.length());  
                        break;  
                    }  
                }  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return macAddress;  
    }  
	public static String getJsonP(HttpServletRequest request,String json){
		String callback=request.getParameter("callback"); 
		return  callback+"("+json+")";
	}
	

}
